<?php
/**
 * Actions modify the AMF message PER BODY
 * This allows batching of calls
 * 
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @copyright (c) 2003 amfphp.org
 * @package flashservices
 * @subpackage filters
 * @version $Id: Actions.php 90 2011-01-16 09:23:26Z nicolas.surian $
 */

/**
 * Catches any special request types and classifies as required
 */
function adapterAction (&$amfbody) {
    $baseClassPath = $GLOBALS['amfphp']['classPath'];

    $uriclasspath = "";
    $classname = "";
    $classpath = "";
    $methodname = "";
    $isWebServiceURI = false;

    $target = $amfbody->targetURI;
    
    if (strpos($target, "http://") === false && strpos($target, "https://") === false) { // check for a http link which means web service
        $lpos = strrpos($target, ".");
        if ($lpos === false) {
            //Check to see if this is in fact a RemotingMessage
            $body = $amfbody->getValue();
            $handled = false;
            
            $messageType = $body[0]->_explicitType;
            if($messageType == 'flex.messaging.messages.RemotingMessage')
            {
                $handled = true;
                
                //Fix for AMF0 mixed array bug in Flex 2
                if(isset($body[0]->body['length']))
                {
                    unset($body[0]->body['length']);
                }
                
                $amfbody->setValue($body[0]->body);
                $amfbody->setSpecialHandling("RemotingMessage");
                $amfbody->setMetadata("clientId", $body[0]->clientId);
                $amfbody->setMetadata("messageId", $body[0]->messageId);
                
                $GLOBALS['amfphp']['lastMessageId'] = $body[0]->messageId;
                
                $methodname = $body[0]->operation;
                $classAndPackage = $body[0]->source;
                $lpos = strrpos($classAndPackage, ".");
                if($lpos !== FALSE)
                {
                    $classname = substr($classAndPackage, $lpos + 1);
                }
                else
                {
                    $classname = $classAndPackage;
                }
                $uriclasspath = str_replace('.','/',$classAndPackage) . '.php';
                $classpath = $baseClassPath . $uriclasspath;
            }
            elseif($messageType == "flex.messaging.messages.CommandMessage")
            {
                if($body[0]->operation == 5)
                {
                    $handled = true;
                    $amfbody->setSpecialHandling("Ping");
                    $amfbody->setMetadata("clientId", $body[0]->clientId);
                    $amfbody->setMetadata("messageId", $body[0]->messageId);
                    $amfbody->noExec = true;
                }
            }
            
            if(!$handled)
            {
                $uriclasspath = "amfphp/Amf3Broker.php";
                $classpath = $baseClassPath . "amfphp/Amf3Broker.php";
                $classname = "Amf3Broker";
                $methodname = "handleMessage";
            }
        } else {
            $methodname = substr($target, $lpos + 1);
            $trunced = substr($target, 0, $lpos);
            $lpos = strrpos($trunced, ".");
            if ($lpos === false) {
                $classname = $trunced;
                if ($classname == "PageAbleResult" && $methodname == 'getRecords') {
                    $val = $amfbody->getValue();
                    $id = $val[0];
                    $keys = explode("=", $id);
                    $currset = intval($keys[1]);
                    
                    $set = $_SESSION['amfphp_recordsets'][$currset];
                    
                    $uriclasspath = $set['class'];
                    $classpath = $baseClassPath . $set['class'];
                    $methodname = $set['method'];
                    
                    $classname = substr(strrchr('/' . $set['class'], '/'), 1, -4);
                    
                    //Now set args for body
                    $amfbody->setValue(array_merge($set['args'], array($val[1], $val[2])));
                    
                    //Tell amfbody that this is a dynamic paged resultset
                    $amfbody->setSpecialHandling('pageFetch');
                } 
                else if($classname == "PageAbleResult" && $methodname == 'release')
                {
                    $amfbody->setSpecialHandling('pageRelease');
                    $amfbody->noExec = true;
                }
                else {
                    $uriclasspath = $trunced . ".php";
                    $classpath = $baseClassPath . $trunced . ".php";
                } 
            } else {
                $classname = substr($trunced, $lpos + 1);
                $classpath = $baseClassPath . str_replace(".", "/", $trunced) . ".php"; // removed to strip the basecp out of the equation here
                $uriclasspath = str_replace(".", "/", $trunced) . ".php"; // removed to strip the basecp out of the equation here
            } 
        }
    } else { // This is a web service and is unsupported
        trigger_error("Web services are not supported in this release", E_USER_ERROR);
    } 

    $amfbody->classPath = $classpath;
    $amfbody->uriClassPath = $uriclasspath;
    $amfbody->className = $classname;
    $amfbody->methodName = $methodname;

    return true;
} 

/**
 * ExecutionAction executes the required methods
 */
function executionAction (&$amfbody) 
{
    $specialHandling = $amfbody->getSpecialHandling();

    if (!$amfbody->isSpecialHandling() || $amfbody->isSpecialHandling(array('describeService', 'pageFetch', 'RemotingMessage')))
    {
        $construct = &$amfbody->getClassConstruct();
        $method = $amfbody->methodName;
        $args = $amfbody->getValue();
        
        if($specialHandling == 'describeService')
        {               
            include_once(AMFPHP_BASE . "util/DescribeService.php");
            $ds = new DescribeService();
            $results = $ds->describe($construct, $amfbody->className);
        }
        else if($specialHandling == 'pageFetch')
        {
            $args[count($args) - 2] = $args[count($args) - 2] - 1;
            
            $dataset = Executive::doMethodCall($amfbody, $construct, $method, $args);
            $results = array("cursor" => $args[count($args) - 2] + 1,
                             "data" => $dataset);
            $amfbody->setMetadata('type', '__DYNAMIC_PAGE__');
        }
        else
        {
            /*
            if(isset($construct->methodTable[$method]['pagesize']))
            {
                //Check if counting method was overriden
                if(isset($construct->methodTable[$method]['countMethod']))
                {
                    $counter = $construct->methodTable[$method]['countMethod'];
                }
                else
                {
                    $counter = $method . '_count';
                }
                
                $dataset = Executive::doMethodCall($amfbody, $construct, $method, $args); // do the magic
                $count = Executive::doMethodCall($amfbody, $construct, $counter, $args);
                
                //Include the wrapper
                $results = array('class' => $amfbody->uriClassPath, 
                                 'method' => $amfbody->methodName, 
                                 'count' => $count, 
                                 "args" => $args, 
                                 "data" => $dataset);
                $amfbody->setMetadata('type', '__DYNAMIC_PAGEABLE_RESULTSET__');
                $amfbody->setMetadata('pagesize', $construct->methodTable[$method]['pagesize']);
                */
            //}
            //else
            //{
                //The usual
                $time = microtime_float();
                $results = Executive::doMethodCall($amfbody, $construct, $method, $args); // do the magic
                global $amfphp;
                $amfphp['callTime'] += microtime_float() - $time;
            //}
        }

        if($results !== '__amfphp_error')
        {
            if($specialHandling == 'RemotingMessage')
            {
                
                $wrapper = new AcknowledgeMessage($amfbody->getMetadata("messageId"), 
                                                  $amfbody->getMetadata("clientId"));
                $wrapper->body = $results;
                $amfbody->setResults($wrapper);
            }
            else
            {
                $amfbody->setResults($results);
            }
            
            $amfbody->responseURI = $amfbody->responseIndex . "/onResult";  
        }
        return false;
    }
    elseif($specialHandling == 'Ping')
    {
        $wrapper = new AcknowledgeMessage($amfbody->getMetadata("messageId"), 
                                          $amfbody->getMetadata("clientId"));
        $amfbody->setResults($wrapper);
        $amfbody->responseURI = $amfbody->responseIndex . "/onResult";
    }
    else if($specialHandling == 'pageRelease')
    {
        //Ignore PageAbleResult.release
        $amfbody->setResults(true);
        $amfbody->setMetaData('type', 'boolean');
        $amfbody->responseURI = $amfbody->responseIndex . "/onResult";
        return false;
    }
    return true;
}
?>